/*
 * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package com.net.NettyEngine3.core;


import com.dc.gameserver.ServerCore.Service.character.PlayerInstance;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;

import java.util.NoSuchElementException;


/**
 * @author : 陈磊 <br/>
 * Date: 12-12-8<br/>
 * Time: 下午6:09<br/>
 * connectMethod:13638363871@163.com<br/>
 *  hand blocking application code such as jdbc , logic and so  on
 *  every client has a NServerFrameHandler  per  2 per
 */
public  class NServerFrameHandler extends SimpleChannelHandler{

    private static final Logger LOG = LoggerFactory.getLogger(NServerFrameHandler.class);

    private ChannelBuffer buffer=null;

    private PlayerInstance player =null;  //玩家对象

    public static BeanFactory springContext;  //spring context

    /**
     *      queue  cached data
     */
    protected NServerFrameHandler(){}


    /**
     *  channel状态处理（超时）
     *  Handler should handle the IdleStateEvent
     *  triggered by IdleStateHandler.
     *  handleUpstream
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
            throws Exception {
        if (e instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent= (IdleStateEvent) e;
            Channel channel=idleStateEvent.getChannel();
            if (idleStateEvent.getState() ==IdleState.READER_IDLE){    //read timeout
                channel.close();
            }else if(idleStateEvent.getState() ==IdleState.WRITER_IDLE){       // netty write timeout
                channel.close();
            }
        } else {
            super.handleUpstream(ctx, e);
        }
    }


    /**
     * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
     * from a remote peer.
     * a task  wait
     * Nio当messageReceived()方法执行后，
     * 如果没有产生异常，worker线程就执行完毕了，worker会被线程池回收
     * 或则调用ExecutionHandler执行业务 ok
     * 处理上行消息  递交逻辑线程处理
     */
    @Override
    public void messageReceived(
            final ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
        if(!(e.getMessage() instanceof ChannelBuffer))return;
        ctx.getChannel().getCloseFuture().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {

            }
        });
        ChannelBuffer buffer= ((ChannelBuffer)e.getMessage());

        /**
         * 业务数据处理
         */

    }
    /**
     * 当建立一个连接时候触发
     * Be aware that this event is fired from within the Boss-Thread so you should not
     * execute any heavy operation in there as it will block the dispatching to other workers!
     *  这个方法在boss线程阻塞，因此不需要做太多的处理
     *  so this is big wrong!!!
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void channelConnected(
            ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        NServerFrameUtil.countConnection.incrementAndGet();

         //spring 管理player
//        this.player= (PlayerInstance) NServerFrameHandler.springContext.getBean("player");
//        this.player.setChannel(e.getChannel());
        ctx.sendUpstream(e);
    }

    /**
     * was closed and all its related resources were released
     * channel关闭触发事件   所有关联的资源都被释放
     * @param ctx     ChannelHandlerContext
     * @param e         ChannelStateEvent
     * @throws Exception    close channel error
     *  1.资源回收
     * 2.持久化数据 ,对象的销毁
     * 3.当对象没有有引用指向该对象时，该对象将会被GC回收
     */
    @Override
    public void channelClosed(
            ChannelHandlerContext ctx, ChannelStateEvent e){

        NServerFrameUtil.countConnection.decrementAndGet();
        ChannelPipeline pipeline=ctx.getPipeline();
        /**保存角色数据*/
//        this.player.save();
        if(null == pipeline){
            return;
        }
        try{
            while(pipeline.getLast()!= null){
                pipeline.removeLast();
            }
        }catch (NoSuchElementException e1){
            // all elements removed.
        }
        ctx.getChannel().close();
    }

    /**
     * 异常处理
     * @param ctx
     * @param e
     * @throws Exception
     */
    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        ctx.getChannel().close();
        ctx.sendUpstream(e);
    }

    public ChannelBuffer getBuffer() {
        return buffer;
    }

    public void setBuffer(ChannelBuffer buffer) {
        this.buffer = buffer;
    }


     /**spring context**/
    public static void setSpringContext(BeanFactory springContext) {
        NServerFrameHandler.springContext = springContext;
    }
}


